#include "Inf_OLED.h"

// #include "driver/i2c.h"
#include "driver/i2c_master.h" 

// 显示屏参数
#define OLED_I2C_ADDRESS 0x3C // 常见的SSD1315地址，也可能是0x3D
#define I2C_MASTER_NUM I2C_NUM_0
#define I2C_MASTER_SDA_IO 8       // GPIO8 作为 SDA
#define I2C_MASTER_SCL_IO 9       // GPIO9 作为 SCL
#define I2C_MASTER_FREQ_HZ 400000 // I2C 时钟频率（400kHz）
// #define WRITE_BIT I2C_MASTER_WRITE
// #define READ_BIT I2C_MASTER_READ
// #define ACK_CHECK_EN 0x1
// #define ACK_CHECK_DIS 0x0
// #define ACK_VAL 0x0
// #define NACK_VAL 0x1

static const char *TAG = "OLED_SSD1315";

// 8x16 基本ASCII字模集
// 每个字符由16个字节表示，按垂直方向排列
const uint8_t font_8x16_basic[][16] = {
    // 数字 0-9
    {0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00}, // '0'
    {0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, // '1'
    {0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00}, // '2'
    {0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00}, // '3'
    {0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00}, // '4'
    {0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00}, // '5'
    {0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00}, // '6'
    {0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // '7'
    {0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00}, // '8'
    {0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00}, // '9'

    // 大写字母 A-Z
    {0x00, 0x00, 0x00, 0xE0, 0x1C, 0x1C, 0xE0, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x23, 0x3C}, // 'A'
    {0x00, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00}, // 'B'
    {0x00, 0xE0, 0x10, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x30, 0x00, 0x00}, // 'C'
    {0x00, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00}, // 'D'
    {0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x08, 0x00, 0x00, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00}, // 'E'
    {0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x08, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'F'
    {0x00, 0xE0, 0x10, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x22, 0x22, 0x13, 0x01}, // 'G'
    {0x00, 0xF8, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00}, // 'H'
    {0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, // 'I'
    {0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0xC0, 0x20, 0x20, 0x20, 0x1F, 0x00, 0x00}, // 'J'
    {0x00, 0xF8, 0x80, 0x80, 0xC0, 0x20, 0x18, 0x00, 0x00, 0x3F, 0x00, 0x01, 0x06, 0x18, 0x20, 0x00}, // 'K'
    {0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00}, // 'L'
    {0x00, 0xF8, 0x18, 0x60, 0x80, 0x60, 0x18, 0xF8, 0x00, 0x3F, 0x00, 0x00, 0x03, 0x00, 0x00, 0x3F}, // 'M'
    {0x00, 0xF8, 0x18, 0x60, 0x80, 0x00, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x01, 0x06, 0x38, 0x00}, // 'N'
    {0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00}, // 'O'
    {0x00, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, // 'P'
    {0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x2F, 0x20}, // 'Q'
    {0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x01, 0x06, 0x38, 0x00}, // 'R'
    {0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00}, // 'S'
    {0x08, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // 'T'
    {0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00}, // 'U'
    {0x00, 0x78, 0x80, 0x00, 0x00, 0x80, 0x78, 0x00, 0x00, 0x00, 0x07, 0x18, 0x18, 0x07, 0x00, 0x00}, // 'V'
    {0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x03, 0x3C, 0x03, 0x00, 0x03, 0x3C, 0x03, 0x00}, // 'W'
    {0x08, 0x18, 0x60, 0x80, 0x80, 0x60, 0x18, 0x08, 0x20, 0x30, 0x0C, 0x03, 0x03, 0x0C, 0x30, 0x20}, // 'X'
    {0x08, 0x38, 0xC0, 0x00, 0xC0, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // 'Y'
    {0x08, 0x08, 0x08, 0x88, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00}, // 'Z'

    // 小写字母 a-z
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x24, 0x24, 0x24, 0x1F, 0x00}, // 'a'
    {0x00, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x04, 0x20, 0x20, 0x20, 0x1F, 0x00}, // 'b'
    {0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x00}, // 'c'
    {0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xF8, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x00}, // 'd'
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x24, 0x24, 0x24, 0x24, 0x0E, 0x00}, // 'e'
    {0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, // 'f'
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6F, 0x90, 0x90, 0x90, 0x90, 0x7F, 0x00}, // 'g'
    {0x00, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x04, 0x20, 0x20, 0x20, 0x1F, 0x00}, // 'h'
    {0x00, 0x80, 0x80, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, // 'i'
    {0x00, 0x80, 0x80, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00}, // 'j'
    {0x00, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x04, 0x0A, 0x11, 0x20, 0x20, 0x00}, // 'k'
    {0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, // 'l'
    {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F}, // 'm'
    {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x04, 0x20, 0x20, 0x20, 0x1F, 0x00}, // 'n'
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00}, // 'o'
    {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0xFF, 0x21, 0x20, 0x20, 0x20, 0x1F, 0x00}, // 'p'
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20}, // 'q'
    {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, // 'r'
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00}, // 's'
    {0x00, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00}, // 't'
    {0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20}, // 'u'
    {0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01, 0x0E, 0x30, 0x30, 0x0E, 0x01, 0x00}, // 'v'
    {0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F}, // 'w'
    {0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x0E, 0x0E, 0x31, 0x20, 0x00}, // 'x'
    {0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00}, // 'y'
    {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00}, // 'z'

    // 特殊字符
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00}, // '.' 小数点
    {0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00}  // ':' 冒号
};

// 定义I2C主机总线句柄和设备句柄（新版本驱动所需）
static i2c_master_bus_handle_t bus_handle;
static i2c_master_dev_handle_t dev_handle;

// 向OLED发送命令（使用新驱动API）
static esp_err_t oled_send_command(uint8_t cmd) {
    // i2c_cmd_handle_t handle = i2c_cmd_link_create();
    // i2c_master_start(handle);
    // i2c_master_write_byte(handle, (OLED_I2C_ADDRESS << 1) | WRITE_BIT, ACK_CHECK_EN);
    // i2c_master_write_byte(handle, 0x00, ACK_CHECK_EN); // 控制字节：Co=0, D/C#=0 (表示命令)
    // i2c_master_write_byte(handle, cmd, ACK_CHECK_EN);
    // i2c_master_stop(handle);
    // esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, handle, pdMS_TO_TICKS(1000));
    // i2c_cmd_link_delete(handle);
    // return ret;

    uint8_t write_buf[2] = {0x00, cmd}; // 控制字节(Co=0, D/C#=0) + 命令字节
    return i2c_master_transmit(dev_handle, write_buf, sizeof(write_buf), -1);
}

// 向OLED发送数据（使用新驱动API）
static esp_err_t oled_send_data(const uint8_t *data, size_t len) {
    // i2c_cmd_handle_t handle = i2c_cmd_link_create();
    // i2c_master_start(handle);
    // i2c_master_write_byte(handle, (OLED_I2C_ADDRESS << 1) | WRITE_BIT, ACK_CHECK_EN);
    // i2c_master_write_byte(handle, 0x40, ACK_CHECK_EN); // 控制字节：Co=0, D/C#=1 (表示数据)
    // i2c_master_write(handle, data, len, ACK_CHECK_EN);
    // i2c_master_stop(handle);
    // esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, handle, pdMS_TO_TICKS(1000));
    // i2c_cmd_link_delete(handle);
    // return ret;

    // 先发送控制字节(Co=0, D/C#=1)，然后跟随数据
    // 新API允许我们将它们组合在一个传输中
    esp_err_t ret;
    size_t data_len_with_control = len + 1;
    uint8_t *write_buf = malloc(data_len_with_control);
    if (write_buf == NULL) {
        return ESP_ERR_NO_MEM;
    }
    write_buf[0] = 0x40; // 控制字节：Co=0, D/C#=1 (表示数据)
    memcpy(&write_buf[1], data, len);
    ret = i2c_master_transmit(dev_handle, write_buf, data_len_with_control, -1);
    free(write_buf);
    return ret;

}

// OLED初始化
static void oled_init() {
    // 初始化序列基于SSD1315，HS96L03W2C03使用这款控制器
    oled_send_command(0xAE); // 关闭显示
    oled_send_command(0x20); // 设置内存地址模式
    oled_send_command(0x00); // 水平地址模式
    oled_send_command(0xB0); // 设置页面起始地址
    oled_send_command(0xC8); // 设置COM输出扫描方向
    oled_send_command(0x00); // 设置低列地址
    oled_send_command(0x10); // 设置高列地址
    oled_send_command(0x40); // 设置显示起始行
    oled_send_command(0x81); // 对比度设置
    oled_send_command(0xFF); // 对比度值（0-255）
    oled_send_command(0xA1); // 设置段重映射（0xA0或0xA1）
    oled_send_command(0xA6); // 正常显示（0xA6=正常，0xA7=反色）
    oled_send_command(0xA8); // 多路复用比率
    oled_send_command(0x3F); // 对于64行显示，值为0x3F
    oled_send_command(0xA4); // 整个显示开启（0xA4=跟随RAM，0xA5=全部开启）
    oled_send_command(0xD3); // 设置显示偏移
    oled_send_command(0x00); // 无偏移
    oled_send_command(0xD5); // 设置显示时钟分频比/振荡器频率
    oled_send_command(0xF0); // 推荐值
    oled_send_command(0xD9); // 设置预充电周期
    oled_send_command(0x22); // 推荐值
    oled_send_command(0xDA); // 设置COM引脚硬件配置
    oled_send_command(0x12); // 对于64行显示，值为0x12
    oled_send_command(0xDB); // 设置VCOMH取消选择级别
    oled_send_command(0x20); // 0x20（默认）
    oled_send_command(0x8D); // 电荷泵设置
    oled_send_command(0x14); // 启用电荷泵（0x14=启用，0x10=禁用）
    oled_send_command(0xAF); // 开启显示
}

// I2C 初始化（使用新驱动API）
static esp_err_t i2c_master_init(void) {
    // i2c_config_t conf = {
    //     .mode = I2C_MODE_MASTER,
    //     .sda_io_num = I2C_MASTER_SDA_IO,
    //     .scl_io_num = I2C_MASTER_SCL_IO,
    //     .sda_pullup_en = GPIO_PULLUP_ENABLE,
    //     .scl_pullup_en = GPIO_PULLUP_ENABLE,
    //     .master.clk_speed = I2C_MASTER_FREQ_HZ,
    // };
    // esp_err_t err = i2c_param_config(I2C_MASTER_NUM, &conf);
    // if (err != ESP_OK) {
    //     return err;
    // }
    // return i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0);

    i2c_master_bus_config_t i2c_bus_config = {
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .i2c_port = I2C_MASTER_NUM,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .glitch_ignore_cnt = 7,
        .flags.enable_internal_pullup = true, // 使用内部上拉（若外部无强上拉）
    };
    
    ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
    
    i2c_device_config_t dev_cfg = {
        .dev_addr_length = I2C_ADDR_BIT_LEN_7,
        .device_address = OLED_I2C_ADDRESS,
        .scl_speed_hz = I2C_MASTER_FREQ_HZ,
    };
    
    ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
    
    ESP_LOGI(TAG, "I2C master bus initialized");
    return ESP_OK;
}

// 清空OLED显示
void oled_clear() {
    uint8_t zero[128] = {0};
    for (uint8_t page = 0; page < 8; page++) {
        oled_send_command(0xB0 + page); // 设置页面地址
        oled_send_command(0x00);        // 设置低列地址
        oled_send_command(0x10);        // 设置高列地址
        oled_send_data(zero, 128);      // 用零填充整行
    }
}

// 获取字符对应的字模数据
const uint8_t *get_char_bitmap_8x16(char c) {
    // 数字 0-9
    if (c >= '0' && c <= '9') {
        return font_8x16_basic[c - '0'];
    }
    // 大写字母 A-Z
    else if (c >= 'A' && c <= 'Z') {
        return font_8x16_basic[10 + (c - 'A')];
    }
    // 小写字母 a-z
    else if (c >= 'a' && c <= 'z') {
        return font_8x16_basic[36 + (c - 'a')];
    }
    // 特殊字符
    else if (c == '.') {
        return font_8x16_basic[62]; // 小数点
    } else if (c == ':') {
        return font_8x16_basic[63]; // 冒号
    }
    // 未知字符返回空格
    static const uint8_t space[16] = {0};
    return space;
}

// 在指定位置显示一个8x16字符
void oled_draw_char(uint8_t x, uint8_t y, char c) {
    const uint8_t *bitmap = get_char_bitmap_8x16(c);

    // 显示上半部分 (前8个字节)
    oled_send_command(0xB0 + y);                 // 设置页面地址
    oled_send_command(0x00 + (x & 0x0F));        // 设置列地址低4位
    oled_send_command(0x10 + ((x >> 4) & 0x0F)); // 设置列地址高4位
    oled_send_data(bitmap, 8);                   // 发送上半部分数据

    // 显示下半部分 (后8个字节)
    oled_send_command(0xB0 + y + 1);             // 设置下一页地址
    oled_send_command(0x00 + (x & 0x0F));        // 设置列地址低4位
    oled_send_command(0x10 + ((x >> 4) & 0x0F)); // 设置列地址高4位
    oled_send_data(bitmap + 8, 8);               // 发送下半部分数据
}

// 显示字符串
void oled_draw_string(uint8_t x, uint8_t y, const char *str) {
    uint8_t current_x = x;
    uint8_t current_y = y;

    while (*str) {
        // 如果超出屏幕右侧，换行
        if (current_x + 8 > 128) {
            current_x = 0;
            current_y += 2; // 8x16字符占用2页高度

            // 如果超出屏幕底部，停止显示
            if (current_y >= 7) { // 最大到第7页(因为8x16字符需要2页)
                break;
            }
        }

        oled_draw_char(current_x, current_y, *str);
        current_x += 8;
        str++;
    }
}

void Inf_OLED_Init(void) {
    ESP_ERROR_CHECK(i2c_master_init());
    ESP_LOGE(TAG, "I2C初始化成功");
    vTaskDelay(pdMS_TO_TICKS(100));

    // 初始化OLED
    oled_init();
    ESP_LOGE(TAG, "OLED初始化完成");
    vTaskDelay(pdMS_TO_TICKS(100));

    // 清空显示
    oled_clear();
    ESP_LOGE(TAG, "显示已清空");
    vTaskDelay(pdMS_TO_TICKS(100));
}
